package com.caiyi.financial.nirvana.sms.cmpp.message;

import com.caiyi.financial.nirvana.sms.cmpp.Message;
import com.caiyi.financial.nirvana.sms.cmpp.message.body.*;
import io.netty.buffer.ByteBuf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;


public abstract class CMPP3Body implements Message {

    private static final Logger logger = LoggerFactory.getLogger(CMPP3Body.class);

    //消息ID与消息类型对应关系
    private static Map<Integer, Class<?>> BODY_TYPE = new HashMap<>();

    //消息注册
    static {
        registerBodyType(CMPP3Message.CMPP_ACTIVE_TEST, CMPP3ActiveTest.class);
        registerBodyType(CMPP3Message.CMPP_ACTIVE_TEST_RESP, CMPP3ActiveTestResp.class);
        registerBodyType(CMPP3Message.CMPP_CONNECT, CMPP3Connection.class);
        registerBodyType(CMPP3Message.CMPP_CONNECT_RESP, CMPP3ConnectionResp.class);
        registerBodyType(CMPP3Message.CMPP_DELIVER, CMPP3Deliver.class);
        registerBodyType(CMPP3Message.CMPP_DELIVER_RESP, CMPP3DeliverResp.class);
        registerBodyType(CMPP3Message.CMPP_SUBMIT, CMPP3Submit.class);
        registerBodyType(CMPP3Message.CMPP_SUBMIT_RESP, CMPP3SubmitResp.class);
        registerBodyType(CMPP3Message.CMPP_TERMINATE, CMPP3Terminate.class);
        registerBodyType(CMPP3Message.CMPP_TERMINATE_RESP, CMPP3TerminateResp.class);
    }

    protected final static void registerBodyType(int commandId, Class<?> bodyType) {
        BODY_TYPE.put(commandId, bodyType);
    }


    /***
     * 空消息体
     */
    public static final CMPP3Body NOOP_BODY = new NOOPBody();


    /***
     * 消息编码到buffer
     * @param buffer
     * @return buffer长度
     */
    public abstract int encode(ByteBuf buffer);


    /***
     *buffer解码为消息体
     * @param buffer
     * @return 消息体
     */
    public abstract CMPP3Body decode(ByteBuf buffer);


    /**
     * 消息体解码
     */
    public static CMPP3Body decodeBody(int commandId, ByteBuf buffer) {
        CMPP3Body body = createBody(commandId);
        body.decode(buffer);
        return body;
    }

    /**
     * 创建消息对象
     *
     * @param commandId
     * @return CMPPBody
     */
    public static CMPP3Body createBody(int commandId) {
        CMPP3Body body = null;
        try {
            body = CMPP3Body.newInstance(commandId);
        } catch (InstantiationException e) {
            logger.error(e.getMessage());
        } catch (IllegalAccessException e) {
            logger.error(e.getMessage());
        }
        return body;
    }


    /**
     * 获取命令ID对应消息类型
     *
     * @param commandId
     * @return
     */
    public final static Class<?> getBodyType(int commandId) {
        return BODY_TYPE.get(commandId);
    }

    /***
     * 根据命令ID生成对应的消息体
     * @param commandId
     * @return
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public static CMPP3Body newInstance(int commandId) throws InstantiationException, IllegalAccessException {
        Class<?> type = getBodyType(commandId);
        if (type == null) {
            return new NOOPBody();
        }
        return (CMPP3Body) type.newInstance();
    }


    /**
     * 空消息体
     *
     * @author zhu_tek
     */
    public static class NOOPBody extends CMPP3Body {
        @Override
        public int encode(ByteBuf buffer) {
            return 0;
        }

        @Override
        public CMPP3Body decode(ByteBuf buffer) {
            return this;
        }
    }
}
